package captcha

import (
	"context"
	"encoding/json"
	"errors"
	"github.com/wenlng/go-captcha-assets/resources/images"
	"github.com/wenlng/go-captcha/v2/base/option"
	"github.com/wenlng/go-captcha/v2/rotate"
	"product/authorization/serve/internal/svc"
	"product/authorization/serve/internal/types"
	"product/common/encryption"

	"github.com/zeromicro/go-zero/core/logx"
)

type CreateRotateCaptchaLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

// NewCreateRotateCaptchaLogic 生成形状验证码
func NewCreateRotateCaptchaLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateRotateCaptchaLogic {
	return &CreateRotateCaptchaLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

// CreateRotateCaptcha 生成旋转验证码
func (l *CreateRotateCaptchaLogic) CreateRotateCaptcha() (resp *types.RotateCaptchaResp, err error) {
	builder, err := initRotateCaptcha()
	if err != nil {
		return &types.RotateCaptchaResp{Ok: false}, err
	}
	captchaData, err := builder.Generate()
	if err != nil {
		return &types.RotateCaptchaResp{Ok: false}, err
	}
	dotData := captchaData.GetData()
	if dotData == nil {
		return &types.RotateCaptchaResp{Ok: false}, errors.New("验证码生成失败")
	}
	var imageBase64, thumbBase64 string
	imageBase64, err = captchaData.GetMasterImage().ToBase64()
	if err != nil {
		return &types.RotateCaptchaResp{Ok: false}, errors.New("图片生成失败")
	}
	thumbBase64, err = captchaData.GetThumbImage().ToBase64()
	if err != nil {
		return &types.RotateCaptchaResp{Ok: false}, errors.New("缩略图生成失败")
	}
	dotByteJson, _ := json.Marshal(dotData)
	key := encryption.Md5ByBytes(dotByteJson)
	_ = l.svcCtx.Redis.SetexCtx(l.ctx, key, string(dotByteJson), 60)
	resp = &types.RotateCaptchaResp{
		CaptchaBase64Image:     imageBase64,
		CaptchCheckBase64Image: thumbBase64,
		CaptchaKey:             key,
		Ok:                     true,
	}
	return resp, nil
}

// initRotateCaptcha 初始化旋转验证码
func initRotateCaptcha() (rotate.Captcha, error) {
	rotateBuilder := rotate.NewBuilder(rotate.WithRangeAnglePos([]option.RangeVal{
		{Min: 20, Max: 30},
	}))
	img, err := images.GetImages()
	if err != nil {
		return nil, err
	}
	rotateBuilder.SetResources(rotate.WithImages(img))
	return rotateBuilder.Make(), nil
}
